# swift/test/lit.cfg - Configuration for the 'lit' test runner -*- python -*-
#
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See https://swift.org/LICENSE.txt for license information
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
#
# -----------------------------------------------------------------------------
#
# This is a configuration file for the 'lit' test runner.
#
# Refer to docs/Testing.rst for documentation.
#
# Update docs/Testing.rst when changing this file.
#
# -----------------------------------------------------------------------------

import os
import platform
import re
import subprocess
import sys
import tempfile
import socket
import glob
import pipes
from distutils.sysconfig import get_python_lib

import lit
import lit.formats
import lit.util

#
# Helper functions.
#

def darwin_get_sdk_version(sdk_path):
    system_version_plist_path = os.path.join(
        sdk_path, "System", "Library", "CoreServices", "SystemVersion.plist")
    name = subprocess.check_output(
        ["defaults", "read", system_version_plist_path,
         "ProductName"]).rstrip()
    vers = subprocess.check_output(
        ["defaults", "read", system_version_plist_path,
         "ProductVersion"]).rstrip()
    build = subprocess.check_output(
        ["defaults", "read", system_version_plist_path,
         "ProductBuildVersion"]).rstrip()
    return (name, vers, build)


def darwin_sdk_build_version_split(version):
    m = re.search("([0-9]+)([A-Z])([0-9]+)", version)
    return (int(m.group(1)), m.group(2), int(m.group(3)))


def darwin_sdk_build_version_cmp(lhs, rhs):
    # The `_cmp` function is provided to port the Python 2 global `cmp`
    # function forward to Python 3. The function implementation is taken
    # directly from the recommendation that announced its removal.
    # See: https://docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons
    def _cmp(a, b):
      return (a > b) - (a < b)
    return _cmp(
        darwin_sdk_build_version_split(lhs),
        darwin_sdk_build_version_split(rhs))


# Run sw_vers on the target to be tested and return the results.
def darwin_get_sw_vers(commandPrefix=[]):
    name = lit.util.executeCommand(
        commandPrefix + ['/usr/bin/sw_vers', '-productName'])[0].rstrip()
    vers = lit.util.executeCommand(
        commandPrefix + ['/usr/bin/sw_vers', '-productVersion'])[0].rstrip()
    build = lit.util.executeCommand(
        commandPrefix + ['/usr/bin/sw_vers', '-buildVersion'])[0].rstrip()
    return (name, vers, build)


# Returns the "prefix" command that should be prepended to the command line to
# run an executable compiled for iOS or AppleTV simulator.
def get_simulator_command(run_os, sdk_path):
    (name, vers, build) = darwin_get_sdk_version(sdk_path)
    if run_os == 'ios':
        # There are two binaries for the iOS simulator: 'sim' and 'simctl'.
        # 'sim' is only supported for iOS <= 8.1 and early versions of 8.2.
        # 'simctl' is supported for iOS >= 8.2.
        # 'simctl' used to have a bug where it failed to propagate the exit
        # code of the child process.  This was fixed only in the middle of 8.2
        # development cycle.
        if ((darwin_sdk_build_version_cmp(build, "12E999") <= 0) or
            (darwin_sdk_build_version_cmp("12F1", build) <= 0 and
             darwin_sdk_build_version_cmp(build, "12F12") <= 0) or
            (darwin_sdk_build_version_cmp("12H1", build) <= 0 and
             darwin_sdk_build_version_cmp(build, "12H11") <= 0)):
            return "sim"
        else:
            return "simctl spawn 'iPhone 6'"
    elif run_os == 'tvos':
        return "simctl spawn 'Apple TV 1080p'"
    elif run_os == 'watchos':
        return "simctl spawn 'Apple Watch - 42mm'"
    else:
        lit_config.fatal("Unknown simulator OS %r" % run_os)

assert darwin_sdk_build_version_cmp("11A1", "12A1") < 0
assert darwin_sdk_build_version_cmp("12A1", "11A1") > 0

assert darwin_sdk_build_version_cmp("11A1", "11B1") < 0
assert darwin_sdk_build_version_cmp("11B1", "11A1") > 0

assert darwin_sdk_build_version_cmp("11A22", "11A100") < 0
assert darwin_sdk_build_version_cmp("11A100", "11A22") > 0

###

# Check that the object root is known.
if config.test_exec_root is None:
    # Otherwise, we haven't loaded the site specific configuration (the user is
    # probably trying to run on a test file directly, and either the site
    # configuration hasn't been created by the build system, or we are in an
    # out-of-tree build situation).

    # Check for 'swift_site_config' user parameter, and use that if available.
    site_cfg = lit_config.params.get('swift_site_config', None)
    if site_cfg and os.path.exists(site_cfg):
        lit_config.load_config(config, site_cfg)
        raise SystemExit

    lit_config.fatal("lit must be pointed at a build folder")

###

class SwiftTest(lit.formats.ShTest, object):
    def __init__(self, coverage_mode=None, execute_external=True):
        super(SwiftTest, self).__init__(execute_external=execute_external)
        if coverage_mode == "FALSE":
            self.coverage_mode = None
        else:
            self.coverage_mode = coverage_mode
        self.skipped_tests = set()

    def before_test(self, test, litConfig):
        _, tmp_base = lit.TestRunner.getTempPaths(test)
        
        # Apparently despite the docs, tmpDir is not actually unique for each test, but
        # tmpBase is.  Remove it here and add a tmpBase substitution in before_test.
        # Speculative fix for rdar://32928464.
        try:
            percentT_index = [x[0] for x in test.config.substitutions].index('%T')
        except ValueError: pass
        else:
            test.config.substitutions.pop(percentT_index)

            test.config.substitutions.append(
                ('%T', '$(mkdir -p %r && echo %r)' % (tmp_base, tmp_base)))

        if self.coverage_mode:
            # FIXME: The compiler crashers run so fast they fill up the
            # merger's queue (and therefore the build bot's disk)
            if 'crasher' in test.getSourcePath():
                test.config.environment["LLVM_PROFILE_FILE"] = os.devnull
                self.skipped_tests.add(test.getSourcePath())
                return
            
            if self.coverage_mode == "NOT_MERGED":
                profdir = tmp_base + '.profdir'
                if not os.path.exists(profdir):
                    os.makedirs(profdir)

                test.config.environment["LLVM_PROFILE_FILE"] = \
                    os.path.join(profdir, "swift-%p.profraw")
            else:
                test.config.environment["LLVM_PROFILE_FILE"] = \
                    os.path.join(config.swift_test_results_dir,
                                 "swift-%4m.profraw")

    def after_test(self, test, litConfig, result):
        if test.getSourcePath() in self.skipped_tests:
            self.skipped_tests.remove(test.getSourcePath())
        return result


    def execute(self, test, litConfig):
        self.before_test(test, litConfig)
        result = super(SwiftTest, self).execute(test, litConfig)
        return self.after_test(test, litConfig, result)

# name: The name of this test suite.
config.name = 'Swift(%s)' % config.variant_suffix[1:]

# Tweak the environment appropriately for various platforms.
if platform.system() == 'Darwin':
    # Prefer the latest version of the Xcode tools.
    config.environment['TOOLCHAINS'] = 'default'

# testFormat: The test format to use to interpret tests.
config.test_format = SwiftTest(coverage_mode=config.coverage_mode)

# suffixes: A list of file extensions to treat as test files.
config.suffixes = ['.swift', '.ll', '.sil', '.gyb', '.m', '.test-sh']

# excludes: A list of directories to exclude from the testsuite. The 'Inputs'
# subdirectories contain auxiliary inputs for various tests in their parent
# directories.
config.excludes = ['Inputs']

if lit_config.params.get('disable_unittests', None) is not None:
    config.excludes += ['Unit']

# test_source_root: The root path where tests are located.
config.test_source_root = os.path.dirname(__file__)

# test_exec_root: The root path where tests should be run.
swift_obj_root = getattr(config, 'swift_obj_root', None)

# Set llvm_{src,obj}_root for use by others.
config.llvm_src_root = getattr(config, 'llvm_src_root', None)
config.llvm_obj_root = getattr(config, 'llvm_obj_root', None)

def append_to_env_path(directory):
    config.environment['PATH'] = \
        os.path.pathsep.join((directory, config.environment['PATH']))

# Tweak the PATH to include the tools dir and the scripts dir.
if swift_obj_root is not None:
    llvm_tools_dir = getattr(config, 'llvm_tools_dir', None)
    if not llvm_tools_dir:
        lit_config.fatal('No LLVM tools dir set!')
    append_to_env_path(llvm_tools_dir)

    build_mode = lit_config.params.get('build_mode', '')
    append_to_env_path(os.path.join(swift_obj_root, build_mode, 'bin'))

native_llvm_tools_path = lit_config.params.get('native_llvm_tools_path')
if native_llvm_tools_path is not None:
    append_to_env_path(native_llvm_tools_path)

native_clang_tools_path = lit_config.params.get('native_clang_tools_path')
if native_clang_tools_path is not None:
    append_to_env_path(native_clang_tools_path)

native_swift_tools_path = lit_config.params.get('native_swift_tools_path')
if native_swift_tools_path is not None:
    append_to_env_path(native_swift_tools_path)

###

# Discover the Swift binaries to use.
def inferSwiftBinary(binaryName):
    # Determine which executable to use.
    envVarName = binaryName.upper().replace("-", "_")
    execPath = os.getenv(envVarName)

    # If the user set the variable in the environment, definitely use that and
    # don't try to validate.
    if execPath:
        return execPath

    # Otherwise look in the path.
    PATH = config.environment['PATH']
    execPath = lit.util.which(binaryName, PATH)

    if execPath:
        if not lit_config.quiet:
            lit_config.note('using %s: %s' % (binaryName, execPath))
    else:
        msg = "couldn't find '%s' program, try setting %s in your environment"
        lit_config.warning(msg % (binaryName, envVarName))

        # Just substitute the plain executable name, so the run line remains
        # reasonable.
        execPath = binaryName

    return execPath

if 'gmalloc' in lit_config.params:
    config.environment['DYLD_INSERT_LIBRARIES'] = '/usr/lib/libgmalloc.dylib'
    config.environment['MALLOC_LOG_FILE'] = '/dev/null'
    config.available_features.add('gmalloc')

# Make inferSwiftBinary() available to be used later on.
config.inferSwiftBinary = inferSwiftBinary

config.swift = inferSwiftBinary('swift')
config.swiftc = inferSwiftBinary('swiftc')
config.sil_opt = inferSwiftBinary('sil-opt')
config.sil_func_extractor = inferSwiftBinary('sil-func-extractor')
config.sil_llvm_gen = inferSwiftBinary('sil-llvm-gen')
config.sil_nm = inferSwiftBinary('sil-nm')
config.sil_passpipeline_dumper = inferSwiftBinary('sil-passpipeline-dumper')
config.lldb_moduleimport_test = inferSwiftBinary('lldb-moduleimport-test')
config.swift_ide_test = inferSwiftBinary('swift-ide-test')
config.swift_syntax_test = inferSwiftBinary('swift-syntax-test')
config.swift_reflection_dump = inferSwiftBinary('swift-reflection-dump')
config.swift_remoteast_test = inferSwiftBinary('swift-remoteast-test')
config.swift_format = inferSwiftBinary('swift-format')
config.clang = inferSwiftBinary('clang')
config.llvm_link = inferSwiftBinary('llvm-link')
config.swift_llvm_opt = inferSwiftBinary('swift-llvm-opt')
config.llvm_profdata = inferSwiftBinary('llvm-profdata')
config.llvm_cov = inferSwiftBinary('llvm-cov')
config.filecheck = inferSwiftBinary('FileCheck')
config.llvm_dwarfdump = inferSwiftBinary('llvm-dwarfdump')

config.swift_utils = os.path.join(config.swift_src_root, 'utils')
config.line_directive = os.path.join(config.swift_utils, 'line-directive')
config.gyb = os.path.join(config.swift_utils, 'gyb')
config.rth = os.path.join(config.swift_utils, 'rth') # Resilience test helper
config.scale_test = os.path.join(config.swift_utils, 'scale-test')
config.PathSanitizingFileCheck = os.path.join(config.swift_utils, 'PathSanitizingFileCheck')
config.swift_lib_dir = os.path.join(os.path.dirname(os.path.dirname(config.swift)), 'lib')
config.round_trip_syntax_test = os.path.join(config.swift_utils, 'round-trip-syntax-test')

# Find the resource directory.  Assume it's near the swift compiler if not set.
test_resource_dir = lit_config.params.get('test_resource_dir')
if test_resource_dir:
    resource_dir_opt = ("-resource-dir %s" % test_resource_dir)
else:
    test_resource_dir = os.path.join(config.swift_lib_dir, 'swift')
    resource_dir_opt = ""
stdlib_resource_dir_opt = resource_dir_opt
lit_config.note('Using resource dir: ' + test_resource_dir)

# Parse the variant triple.
(run_cpu, run_vendor, run_os, run_vers) = re.match('([^-]+)-([^-]+)-([^0-9]+)(.*)', config.variant_triple).groups()
run_ptrsize = '64' if ('64' in run_cpu or run_cpu == "s390x") else '32'

sdk_overlay_link_path = ""
sdk_overlay_linker_opt = ""
sdk_overlay_dir_opt = ""
test_sdk_overlay_dir = lit_config.params.get('test_sdk_overlay_dir', None)
if test_sdk_overlay_dir is not None:
    sdk_overlay_dir_opt = ("-I %s" % os.path.join(test_sdk_overlay_dir, run_cpu))
    sdk_overlay_link_path_dir = os.path.join(test_sdk_overlay_dir, run_cpu)
    sdk_overlay_link_path = ("-L %s" % sdk_overlay_link_path_dir)
    sdk_overlay_linker_opt = (
        "-L %s -Xlinker -rpath -Xlinker %s" %
        (sdk_overlay_link_path_dir, sdk_overlay_link_path_dir))
    lit_config.note('Using SDK overlay dir: ' + test_sdk_overlay_dir)
    resource_dir_opt += (" %s" % sdk_overlay_dir_opt)

# Default to Swift 3 for now.
# Note that this accepts both `--param swift-version` (like the compiler flag)
# and `--param swift_version` (like a lit configuration parameter).
swift_version = lit_config.params.get('swift-version',
    lit_config.params.get('swift_version', '3'))
lit_config.note('Compiling with -swift-version ' + swift_version)
config.swift_test_options = '-swift-version ' + swift_version

test_options = os.environ.get('SWIFT_TEST_OPTIONS')
if test_options:
    config.swift_test_options += ' '
    config.swift_test_options += test_options

config.sil_test_options = os.environ.get('SIL_TEST_OPTIONS')
if not config.sil_test_options:
    config.sil_test_options = ''

clang_module_cache_path = tempfile.mkdtemp(prefix="swift-testsuite-clang-module-cache")
mcp_opt = "-module-cache-path %r" % clang_module_cache_path
clang_mcp_opt = "-fmodules-cache-path=%r" % clang_module_cache_path
lit_config.note("Using Clang module cache: " + clang_module_cache_path)
lit_config.note("Using test results dir: " + config.swift_test_results_dir)

completion_cache_path = tempfile.mkdtemp(prefix="swift-testsuite-completion-cache")
ccp_opt = "-completion-cache-path %r" % completion_cache_path
lit_config.note("Using code completion cache: " + completion_cache_path)

config.substitutions.append( ('%swift_obj_root', config.swift_obj_root) )
config.substitutions.append( ('%swift_src_root', config.swift_src_root) )
config.substitutions.append( ('%{python}', sys.executable) )
config.substitutions.append( ('%mcp_opt', mcp_opt) )
config.substitutions.append( ('%swift_driver_plain', "%r" % config.swift) )
config.substitutions.append( ('%swiftc_driver_plain', "%r" % config.swiftc) )
config.substitutions.append( ('%swift_driver', "env SDKROOT= %r %s %s" % (config.swift, mcp_opt, config.swift_test_options)) )
config.substitutions.append( ('%swiftc_driver', "env SDKROOT= %r %s %s" % (config.swiftc, mcp_opt, config.swift_test_options)) )
config.substitutions.append( ('%sil-opt', "%r %s %s" % (config.sil_opt, mcp_opt, config.sil_test_options)) )
config.substitutions.append( ('%sil-func-extractor', "%r %s" % (config.sil_func_extractor, mcp_opt)) )
config.substitutions.append( ('%sil-llvm-gen', "%r %s" % (config.sil_llvm_gen, mcp_opt)) )
config.substitutions.append( ('%sil-nm', "%r %s" % (config.sil_nm, mcp_opt)) )
config.substitutions.append( ('%sil-passpipeline-dumper', "%r" % (config.sil_passpipeline_dumper)) )
config.substitutions.append( ('%lldb-moduleimport-test', "%r %s" % (config.lldb_moduleimport_test, mcp_opt)) )
config.substitutions.append( ('%swift-ide-test_plain', config.swift_ide_test) )
config.substitutions.append( ('%swift-ide-test', "%r %s %s -swift-version %s" % (config.swift_ide_test, mcp_opt, ccp_opt, swift_version)) )
config.substitutions.append( ('%swift-syntax-test', config.swift_syntax_test) )
config.substitutions.append( ('%swift-format', config.swift_format) )
config.substitutions.append( ('%llvm-link', config.llvm_link) )
config.substitutions.append( ('%swift-llvm-opt', config.swift_llvm_opt) )
config.substitutions.append( ('%llvm-dwarfdump', config.llvm_dwarfdump) )

# This must come after all substitutions containing "%swift".
config.substitutions.append(
    ('%swift',
     "%r -frontend %s -disable-objc-attr-requires-foundation-module %s"
       % (config.swift, mcp_opt, config.swift_test_options)) )

config.clang_include_dir = \
  os.path.join(os.path.dirname(os.path.dirname(config.swift)), 'include')
config.substitutions.append( ('%clang-include-dir', config.clang_include_dir) )

# Use this to build the basic set of Objective-C overlays.
config.substitutions.append(
    ('%build-clang-importer-objc-overlays',
  '%target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -o %t %clang-importer-sdk-path/swift-modules/ObjectiveC.swift && '
  '%target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -o %t %clang-importer-sdk-path/swift-modules/CoreGraphics.swift && '
  '%target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -o %t %clang-importer-sdk-path/swift-modules/Foundation.swift'))

# FIXME: BEGIN -enable-source-import hackaround
config.substitutions.append(
    ('%clang-importer-sdk-path',
     '%r/Inputs/clang-importer-sdk' %
        (config.test_source_root) ) )

config.substitutions.append(
    ('%clang-importer-sdk-nosource',
     '-sdk %r/Inputs/clang-importer-sdk ' %
        (config.test_source_root) ) )
# FIXME: END -enable-source-import hackaround

config.substitutions.append(
    ('%clang-importer-sdk',
     '-enable-source-import '
     '-sdk %r/Inputs/clang-importer-sdk '
     '-I %r/Inputs/clang-importer-sdk/swift-modules ' %
        (config.test_source_root, config.test_source_root) ) )

config.substitutions.append( ('%clang_apinotes',
                              "%r -cc1apinotes" %
                                (config.clang)) )

# This must come after all substitutions containing "%clang".
# Note: %clang is the locally-built clang.
# To get Xcode's clang, use %target-clang.
config.substitutions.append( ('%clang',
                              "%r %r" %
                                (config.clang, clang_mcp_opt)) )

###

def disallow(execName):
  warning = '''
    echo '*** Do not use \'{0}\' in tests; use \'%''{0}\'. ***' &&
    exit 1 && echo
  '''
  config.substitutions.append((' {0} '.format(execName),
                               warning.format(execName)))

disallow('swift')
disallow('swiftc')
disallow('swift_driver')
disallow('swiftc_driver')
disallow('sil-opt')
disallow('sil-func-extractor')
disallow('sil-llvm-gen')
disallow('sil-nm')
disallow('sil-passpipeline-dumper')
disallow('lldb-moduleimport-test')
disallow('swift-ide-test')
disallow('clang')
disallow('FileCheck')
disallow('llvm-dwarfdump')

config.substitutions.insert(0,
    ('%p',
     '$(echo "*** Use %""S instead of %""p in the Swift test suite ***" >&2)'))

###

# Set available features we allow tests to conditionalize on.
if platform.system() != 'Windows':
    config.available_features.add('crash-recovery')

# Add each available build target CPU as a feature.
for target in config.llvm_code_generators:
  config.available_features.add("CODEGENERATOR=" + target)

# Add the run target CPU, OS, and pointer size as features.
config.available_features.add("CPU=" + run_cpu)
config.available_features.add("OS=" + run_os)
config.available_features.add("PTRSIZE=" + run_ptrsize)

if run_cpu == "i386" or run_cpu == "x86_64":
  config.available_features.add("CPU=i386_or_x86_64")

config.available_features.add("SWIFT_VERSION=" + swift_version)

if "optimized_stdlib" in config.available_features:
  config.available_features.add("optimized_stdlib_" + run_cpu)

swift_test_mode = lit_config.params.get('swift_test_mode', 'optimize_none')
swift_execution_tests_extra_flags = ''
if swift_test_mode == 'optimize_none':
    config.available_features.add("nonexecutable_test")
    config.available_features.add("executable_test")
    config.available_features.add("swift_test_mode_optimize_none")
    # Add the cpu as a feature so we can selectively disable tests in an
    # optimize mode for a cpu.
    config.available_features.add("swift_test_mode_optimize_none_" + run_cpu)
    swift_execution_tests_extra_flags = ''
elif swift_test_mode == 'optimize':
    config.available_features.add("executable_test")
    config.limit_to_features.add("executable_test")
    config.available_features.add("swift_test_mode_optimize")
    # Add the cpu as a feature so we can selectively disable tests in an
    # optimize mode for a cpu.
    config.available_features.add("swift_test_mode_optimize_" + run_cpu)
    swift_execution_tests_extra_flags = '-O'
elif swift_test_mode == 'optimize_unchecked':
    config.available_features.add("executable_test")
    config.limit_to_features.add("executable_test")
    config.available_features.add("swift_test_mode_optimize_unchecked")
    # Add the cpu as a feature so we can selectively disable tests in an
    # optimize mode for a cpu.
    config.available_features.add("swift_test_mode_optimize_unchecked_" + run_cpu)
    swift_execution_tests_extra_flags = '-Ounchecked'
elif swift_test_mode == 'only_executable':
    config.available_features.add("executable_test")
    config.limit_to_features.add("executable_test")
elif swift_test_mode == 'only_non_executable':
    config.available_features.add("nonexecutable_test")
else:
    lit_config.fatal("Unknown test mode %r" % swift_test_mode)

swift_test_subset = lit_config.params.get('swift_test_subset', 'validation')
if swift_test_subset in ['primary', 'validation', 'only_validation']:
    # No extra flags needed.
    pass
elif swift_test_subset == 'all':
    config.available_features.add("long_test")
elif swift_test_subset == 'only_long':
    config.available_features.add("long_test")
    config.limit_to_features.add("long_test")
    config.limit_to_features.discard("executable_test")
else:
    lit_config.fatal("Unknown test mode %r" % swift_test_subset)

# Add substitutions for the run target triple, CPU, OS, and pointer size.
config.substitutions.append(('%target-triple', config.variant_triple))

# Sanitizers are not supported on iOS7, yet all tests are configured to start
# testing with the earliest supported platform, which happens to be iOS7 for
# Swift.
# Setting target manually makes tests less versatile (a separate test is
# then required for each OS), thus instead we define a new environment
# variable which enforces the usage of iOS8+ when iOS is used.
config.substitutions.append(('%sanitizers-target-triple',
    config.variant_triple.replace("ios7", "ios8")))

config.substitutions.append(('%target-cpu', run_cpu))
config.substitutions.append(('%target-os', run_os))
config.substitutions.append(('%target-ptrsize', run_ptrsize))

# Enable Darwin SDK-dependent tests if we have an SDK.
# On Linux, assume that SDK path does not point to the Darwin SDK.
if config.variant_sdk != "":
  config.substitutions.append(('%sdk', '"%s"' % config.variant_sdk))

# Enable interpreter-based tests on platforms where the interpreter is known to
# work.
if platform.system() == 'Darwin' and (run_os == 'macosx' or run_os == 'darwin'):
    # Disable REPL tests if SDK overlay is not in the resource dir.
    # <rdar://problem/16678410> Adding more libraries with -lfoo to REPL is broken
    config.available_features.add('swift_repl')
    config.available_features.add('swift_interpreter')
elif platform.system() == 'Linux':
    config.available_features.add('swift_interpreter')

# swift-remoteast-test requires the ability to compile and run code
# for the system we compiled the swift-remoteast-test executable on.
# This is potentially a stronger constraint than just "can we interpret",
# but use that as an approximation for now.
if 'swift_interpreter' in config.available_features:
    config.available_features.add('swift-remoteast-test')

config.target_swiftmodule_name = "unknown.swiftmodule"
config.target_swiftdoc_name = "unknown.swiftdoc"
config.target_runtime = "unknown"

if run_vendor == 'apple':
    config.available_features.add('objc_interop')
    config.target_swiftmodule_name = run_cpu + ".swiftmodule"
    config.target_swiftdoc_name = run_cpu + ".swiftdoc"
    config.target_object_format = "macho"
    config.target_dylib_extension = "dylib"
    config.target_runtime = "objc"

    xcrun_prefix = (
        "xcrun --toolchain %s --sdk %s" %
        (config.darwin_xcrun_toolchain, config.variant_sdk))
    extra_frameworks_dir = os.path.join(config.variant_sdk,
        "..", "..", "..", "Developer", "Library", "Frameworks")
    target_options = (
        "-target %s %s %s" %
        (config.variant_triple, resource_dir_opt, mcp_opt))
    target_options_for_mock_sdk = (
        "-target %s %s %s" %
        (config.variant_triple, stdlib_resource_dir_opt, mcp_opt))
    target_options_for_mock_sdk_after = sdk_overlay_dir_opt

    if 'arm' in run_cpu and swift_test_mode != 'only_non_executable':
        raise RuntimeError('Device tests are not currently supported.')

    if 'arm' in run_cpu:
       # iOS/tvOS/watchOS device
       if run_os == 'ios':
           lit_config.note('Testing iOS ' + config.variant_triple)
           xcrun_sdk_name = "iphoneos"
       elif run_os == 'tvos':
           lit_config.note('Testing AppleTV ' + config.variant_triple)
           xcrun_sdk_name = "appletvos"
       elif run_os == 'watchos':
           lit_config.note('Testing watchOS ' + config.variant_triple)
           xcrun_sdk_name = "watchos"

       if run_cpu == "armv7" or run_cpu == "armv7s" or run_cpu == "armv7k":
           config.target_swiftmodule_name = "arm.swiftmodule"
           config.target_swiftdoc_name = "arm.swiftdoc"
       elif run_cpu == "arm64":
           config.target_swiftmodule_name = "arm64.swiftmodule"
           config.target_swiftdoc_name = "arm64.swiftdoc"
       else:
           lit_config.fatal("Unknown CPU '%s'" % run_cpu)

       config.target_cc_options = (
           "-arch %s -m%s-version-min=%s %s" %
           (run_cpu, run_os, run_vers, clang_mcp_opt))

       config.target_build_swift = (
           "%s %s %s -F %s -Xlinker -rpath -Xlinker %s %s %s %s" %
           (xcrun_prefix, config.swiftc, target_options,
            extra_frameworks_dir,
            "/tmp/swifttest-device/lib",
            sdk_overlay_linker_opt, config.swift_test_options,
            swift_execution_tests_extra_flags))
       config.target_run = "unsupported"

       (sw_vers_name, sw_vers_vers, sw_vers_build) = \
            darwin_get_sdk_version(config.variant_sdk)

    elif run_os == 'ios' or run_os == 'tvos' or run_os == 'watchos':
        # iOS/tvOS/watchOS simulator
        if run_os == 'ios':
            lit_config.note("Testing iOS simulator " + config.variant_triple)
            xcrun_sdk_name = "iphonesimulator"
        elif run_os == 'watchos':
            lit_config.note("Testing watchOS simulator " + config.variant_triple)
            xcrun_sdk_name = "watchsimulator"
        else:
            lit_config.note("Testing AppleTV simulator " + config.variant_triple)
            xcrun_sdk_name = "appletvsimulator"

        config.target_cc_options = (
            "-arch %s -m%s-simulator-version-min=%s %s" %
            (run_cpu, run_os, run_vers, clang_mcp_opt))

        config.target_build_swift = (
            "%s %s %s -F %s %s %s %s" %
            (xcrun_prefix, config.swiftc, target_options,
             extra_frameworks_dir,
             sdk_overlay_linker_opt, config.swift_test_options,
             swift_execution_tests_extra_flags))
        # FIXME: allow specification of simulator and version
        #
        # Note: don't pass '--adopt-pid' to sim.  This can trigger a kernel
        # panic.
        # <rdar://problem/11806093> multithreaded 64-to-32 exec is broken
        # (foundation tool launched with sim --adopt-pid occasionally
        # segmentation faults)
        config.target_run = (
            "%s %s " %
            (xcrun_prefix, get_simulator_command(run_os, config.variant_sdk)))

        (sw_vers_name, sw_vers_vers, sw_vers_build) = \
            darwin_get_sdk_version(config.variant_sdk)

        if (sw_vers_name == '' or sw_vers_vers == '' or sw_vers_build == ''):
            lit_config.fatal('Could not get or decode sw_vers output. ' +
                             'Perhaps the simulator is not working.')

    elif run_os == 'macosx':
        # OS X
        lit_config.note("Testing OS X " + config.variant_triple)

        xcrun_sdk_name = "macosx"
        config.target_cc_options = (
            "-arch %s -m%s-version-min=%s %s" %
            (run_cpu, run_os, run_vers, clang_mcp_opt))

        config.target_build_swift = (
            "%s %s %s -F %s -Xlinker -rpath -Xlinker %s %s %s %s"
            % (xcrun_prefix, config.swiftc, target_options,
               extra_frameworks_dir, extra_frameworks_dir,
               sdk_overlay_linker_opt, config.swift_test_options,
               swift_execution_tests_extra_flags))
        config.target_run = ""

        if 'interpret' in lit_config.params:
            target_run_base = (
                '%s %s %s -module-name main %s %s'
                % (xcrun_prefix, config.swift, target_options,
                   config.swift_test_options,
                   swift_execution_tests_extra_flags))
            config.target_run_simple_swift = (
                "%s %%s" % (target_run_base))
            config.target_run_stdlib_swift = (
                "%s -Xfrontend -disable-access-control %%s" % (target_run_base))
            config.target_run_simple_swiftgyb = (
                'rm -rf %%t && mkdir -p %%t && '
                '%%gyb %%s -o %%t/main.swift && '
                '%%line-directive %%t/main.swift -- %s %%t/main.swift'
                % (target_run_base))
            config.available_features.add('interpret')
            config.environment['SWIFT_INTERPRETER'] = config.swift

        (sw_vers_name, sw_vers_vers, sw_vers_build) = \
            darwin_get_sw_vers()

    else:
        lit_config.fatal("Unknown Apple OS '" + run_os + "' " +
                         "(from " + config.variant_triple + ")")

    lit_config.note(
        'Running tests on %s version %s (%s)' %
        (sw_vers_name, sw_vers_vers, sw_vers_build))

    config.target_sdk_name = xcrun_sdk_name
    config.target_ld = (
        "%s ld -L%s" %
        (xcrun_prefix, os.path.join(test_resource_dir, config.target_sdk_name)))
    config.target_swift_frontend = (
        "%s -frontend %s -sdk %s %s" %
        (config.swiftc, target_options, config.variant_sdk,
         config.swift_test_options))
    subst_target_swift_frontend_mock_sdk = (
        "%s -frontend %s -sdk %s %s" %
        (config.swiftc, target_options_for_mock_sdk, config.variant_sdk,
         config.swift_test_options))
    config.target_swift_modulewrap = (
        '%s -modulewrap -target %s' %
        (config.swiftc, config.variant_triple))
    subst_target_swift_frontend_mock_sdk_after = \
        target_options_for_mock_sdk_after
    config.target_sil_opt = (
        "%s %s %s %s" %
        (xcrun_prefix, config.sil_opt, target_options, config.sil_test_options))
    config.target_swift_ide_test = (
        "%s %s %s %s" %
        (xcrun_prefix, config.swift_ide_test, target_options, ccp_opt))
    subst_target_swift_ide_test_mock_sdk = (
        "%s %s %s %s" %
        (xcrun_prefix, config.swift_ide_test, target_options_for_mock_sdk, ccp_opt))
    subst_target_swift_ide_test_mock_sdk_after = \
        target_options_for_mock_sdk_after
    config.target_swiftc_driver = (
        "%s %s %s" %
        (xcrun_prefix, config.swiftc, target_options))
    config.target_clang = (
        "%s clang++ %s" %
        (xcrun_prefix, config.target_cc_options))

elif run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'windows-cygnus', 'windows-gnu']:
    # Linux/FreeBSD/Cygwin
    if run_os == 'windows-cygnus':
      lit_config.note("Testing Cygwin " + config.variant_triple)
      config.target_object_format = "coff"
      config.target_dylib_extension = "dll"
      config.target_sdk_name = "cygwin"
    elif run_os == 'windows-gnu':
      lit_config.note("Testing MinGW " + config.variant_triple)
      config.target_object_format = "coff"
      config.target_dylib_extension = "dll"
      config.target_sdk_name = "mingw"
    elif run_os == 'freebsd':
      lit_config.note("Testing FreeBSD " + config.variant_triple)
      config.target_object_format = "elf"
      config.target_dylib_extension = "so"
      config.target_sdk_name = "freebsd"
    else:
      lit_config.note("Testing Linux " + config.variant_triple)
      config.target_object_format = "elf"
      config.target_dylib_extension = "so"
      config.target_sdk_name = "linux"
    config.target_runtime = "native"
    config.target_swift_autolink_extract = inferSwiftBinary("swift-autolink-extract")
    config.target_build_swift = (
        '%s -target %s %s %s %s %s'
        % (config.swiftc, config.variant_triple, resource_dir_opt, mcp_opt,
           config.swift_test_options, swift_execution_tests_extra_flags))
    config.target_swift_frontend = (
        '%s -frontend -target %s %s %s %s'
        % (config.swift, config.variant_triple, resource_dir_opt, mcp_opt,
        config.swift_test_options))
    subst_target_swift_frontend_mock_sdk = config.target_swift_frontend
    subst_target_swift_frontend_mock_sdk_after = ""
    config.target_run = ''
    if 'interpret' in lit_config.params:
        target_run_base = (
            '%s -target %s %s %s -module-name main %s %s'
            % (config.swift, config.variant_triple, resource_dir_opt,
               mcp_opt, config.swift_test_options,
               swift_execution_tests_extra_flags))
        config.target_run_simple_swift = (
            '%s %%s' % (target_run_base))
        config.target_run_stdlib_swift = (
            '%s -Xfrontend -disable-access-control %%s' % (target_run_base))
        config.target_run_simple_swiftgyb = (
            'rm -rf %%t && mkdir -p %%t && '
            '%%gyb %%s -o %%t/main.swift && '
            '%%line-directive %%t/main.swift -- %s %%t/main.swift'
            % (target_run_base))
        config.available_features.add('interpret')
        config.environment['SWIFT_INTERPRETER'] = config.swift
    config.target_sil_opt = (
        '%s -target %s %s %s %s' %
        (config.sil_opt, config.variant_triple, resource_dir_opt, mcp_opt, config.sil_test_options))
    config.target_swift_ide_test = (
        '%s -target %s %s %s %s' %
        (config.swift_ide_test, config.variant_triple, resource_dir_opt,
         mcp_opt, ccp_opt))
    subst_target_swift_ide_test_mock_sdk = config.target_swift_ide_test
    subst_target_swift_ide_test_mock_sdk_after = ""
    config.target_swiftc_driver = (
        "%s -target %s %s %s" %
        (config.swiftc, config.variant_triple, resource_dir_opt, mcp_opt))
    config.target_swift_modulewrap = (
        '%s -modulewrap -target %s' %
        (config.swiftc, config.variant_triple))
    config.target_clang = (
        "clang++ -target %s %s" %
        (config.variant_triple, clang_mcp_opt))
    config.target_ld = (
        "ld -L%s" %
        (os.path.join(test_resource_dir, config.target_sdk_name)))
elif run_os == 'linux-androideabi':
    lit_config.note("Testing Android " + config.variant_triple)
    config.target_object_format = "elf"
    config.target_dylib_extension = "so"
    config.target_runtime = "native"
    config.target_swift_autolink_extract = inferSwiftBinary("swift-autolink-extract")
    config.target_sdk_name = "android"
    android_linker_opt = "-L {libcxx} -L {libgcc}".format(
        libcxx=os.path.join(config.android_ndk_path,
                            "sources", "cxx-stl", "llvm-libc++", "libs",
                            "armeabi-v7a"),
        libgcc=os.path.join(config.android_ndk_path,
                            "toolchains",
                            "arm-linux-androideabi-{}".format(
                                config.android_ndk_gcc_version),
                            "prebuilt", "linux-x86_64", "lib", "gcc",
                            "arm-linux-androideabi",
                            "{}.x".format(config.android_ndk_gcc_version)))
    config.target_build_swift = (
        '%s -target %s -sdk %s %s -Xlinker -pie %s %s %s %s'
        % (config.swiftc, config.variant_triple, config.variant_sdk,
           android_linker_opt, resource_dir_opt, mcp_opt,
           config.swift_test_options, swift_execution_tests_extra_flags))
    config.target_swift_frontend = (
        '%s -frontend -target %s -sdk %s %s %s %s'
        % (config.swift, config.variant_triple, config.variant_sdk,
           android_linker_opt, resource_dir_opt, mcp_opt))
    subst_target_swift_frontend_mock_sdk = config.target_swift_frontend
    subst_target_swift_frontend_mock_sdk_after = ""
    config.target_run = os.path.join(
        config.swift_src_root, 'utils', 'android', 'adb_test_runner.py')
    # FIXME: Include -sdk in this invocation.
    config.target_sil_opt = (
        '%s -target %s %s %s %s' %
        (config.sil_opt, config.variant_triple, resource_dir_opt, mcp_opt, config.sil_test_options))
    config.target_swift_ide_test = (
        '%s -target %s %s %s %s' %
        (config.swift_ide_test, config.variant_triple, resource_dir_opt,
         mcp_opt, ccp_opt))
    subst_target_swift_ide_test_mock_sdk = config.target_swift_ide_test
    subst_target_swift_ide_test_mock_sdk_after = ""
    config.target_swiftc_driver = (
        "%s -target %s -sdk %s %s %s %s" %
        (config.swiftc, config.variant_triple, config.variant_sdk,
         android_linker_opt, resource_dir_opt, mcp_opt))
    config.target_swift_modulewrap = (
        '%s -modulewrap -target %s' %
        (config.swiftc, config.variant_triple))
    config.target_clang = (
        "clang++ -target %s %s" %
        (config.variant_triple, clang_mcp_opt))
    config.target_ld = "{} -L{}".format(
        os.path.join(
            config.android_ndk_path,
            'toolchains',
            'arm-linux-androideabi-{}'.format(config.android_ndk_gcc_version),
            'prebuilt',
            'linux-x86_64',
            'arm-linux-androideabi',
            'bin'),
        os.path.join(test_resource_dir, config.target_sdk_name))
    # The Swift interpreter is not available when targeting Android.
    config.available_features.remove('swift_interpreter')

else:
    lit_config.fatal("Don't know how to define target_run and "
                     "target_build_swift for platform " + config.variant_triple)


# Different OS's require different prefixes for the environment variables to be
# propagated to the calling contexts.
# In order to make tests OS-agnostic, names of environment variables should be
# prefixed with `%env-`, which is then expanded to the appropriate prefix.
SIMULATOR_ENV_PREFIX = 'SIMCTL_CHILD_'
ENV_VAR_PREFIXES = {
    'iphonesimulator': SIMULATOR_ENV_PREFIX,
    'watchsimulator': SIMULATOR_ENV_PREFIX,
    'appletvsimulator': SIMULATOR_ENV_PREFIX
}
config.substitutions.append(('%env-', ENV_VAR_PREFIXES.get(config.target_sdk_name, "")))
config.substitutions.append(("%target-sdk-name", config.target_sdk_name))

config.compiler_rt_libs = []
config.compiler_rt_platform = {
    'iphoneos': 'ios',
    'appletvos': 'tvos',
    'watchos': 'watchos',
    'iphonesimulator': 'iossim',
    'watchsimulator': 'watchossim',
    'appletvsimulator': 'tvossim',
    'macosx': 'osx'
}.get(config.target_sdk_name, run_cpu)

def source_compiler_rt_libs(path):
    if os.path.exists(path):
        config.compiler_rt_libs.extend([lib for lib in
                                        os.listdir(path)
                                        if lib.startswith('libclang_rt.')
                                        and config.compiler_rt_platform in lib])

source_compiler_rt_libs(os.path.join(test_resource_dir, 'clang', 'lib',
                        platform.system().lower()))

def check_runtime_feature(name):
    for lib in config.compiler_rt_libs:
        if lib.startswith('libclang_rt.' + name + '_'):
            config.available_features.add(name + '_runtime')
            return

check_runtime_feature('profile')
check_runtime_feature('asan')
check_runtime_feature('ubsan')
check_runtime_feature('tsan')
check_runtime_feature('safestack')

if not getattr(config, 'target_run_simple_swift', None):
    config.target_run_simple_swift = (
        'rm -rf %%t && mkdir -p %%t && '
        '%s %s %%s -o %%t/a.out -module-name main && '
        '%s %%t/a.out'
        % (config.target_build_swift, mcp_opt, config.target_run))
    config.target_run_stdlib_swift = (
        'rm -rf %%t && mkdir -p %%t && '
        '%s %s %%s -o %%t/a.out -module-name main '
        '-Xfrontend -disable-access-control && '
        '%s %%t/a.out'
        % (config.target_build_swift, mcp_opt, config.target_run))
    config.target_run_simple_swiftgyb = (
        'rm -rf %%t && mkdir -p %%t && '
        '%%gyb %%s -o %%t/main.swift && '
        '%%line-directive %%t/main.swift -- '
        '%s %s %%t/main.swift -o %%t/a.out -module-name main && '
        '%%line-directive %%t/main.swift -- '
        '%s %%t/a.out'
        % (config.target_build_swift, mcp_opt, config.target_run))

subst_target_jit_run = ""
if 'swift_interpreter' in config.available_features:
    subst_target_jit_run = (
        "%s -interpret %s" %
        (config.target_swift_frontend, sdk_overlay_link_path))

subst_target_repl_run_simple_swift = ""
if 'swift_repl' in config.available_features:
    subst_target_repl_run_simple_swift = (
        "%s -repl %s < %%s 2>&1" %
        (config.target_swift_frontend, sdk_overlay_link_path))

config.target_parse_verify_swift = (
    '%s -typecheck -verify -disable-objc-attr-requires-foundation-module %%s'
    % (config.target_swift_frontend, ))

config.target_sil_func_extractor = (
    '%s -target %s %s'
    % (config.sil_func_extractor, config.variant_triple, mcp_opt))

config.target_sil_llvm_gen = (
    '%s -target %s %s'
    % (config.sil_llvm_gen, config.variant_triple, mcp_opt))

config.target_sil_nm= (
    '%s -target %s %s'
    % (config.sil_nm, config.variant_triple, mcp_opt))

config.target_resilience_test_wmo = (
     ('%s --target-build-swift "%s" --target-run "%s" --t %%t --S %%S --s %%s '
      '--additional-compile-flags-library "-whole-module-optimization -parse-as-library"')
     % (config.rth, config.target_build_swift, config.target_run))

config.target_resilience_test = (
     '%s --target-build-swift "%s" --target-run "%s" --t %%t --S %%S --s %%s'
     % (config.rth, config.target_build_swift, config.target_run))

#
# When changing substitutions, update docs/Testing.rst.
#

config.substitutions.append(('%target-runtime', config.target_runtime))

config.substitutions.append(('%target-typecheck-verify-swift', config.target_parse_verify_swift))

config.substitutions.append(
    ('%target-swift-frontend\(mock-sdk:([^)]+)\)',
     '%s \\1 %s' %
     (subst_target_swift_frontend_mock_sdk,
      subst_target_swift_frontend_mock_sdk_after)))
config.substitutions.append(('%target-swift-frontend', config.target_swift_frontend))


config.substitutions.append(('%target-run-simple-swiftgyb', config.target_run_simple_swiftgyb))
config.substitutions.append(('%target-run-simple-swift', config.target_run_simple_swift))
config.substitutions.append(('%target-run-stdlib-swift', config.target_run_stdlib_swift))
config.substitutions.append(('%target-repl-run-simple-swift', subst_target_repl_run_simple_swift))
config.substitutions.append(('%target-run', config.target_run))
config.substitutions.append(('%target-jit-run', subst_target_jit_run))
config.substitutions.append(('%target-build-swift', config.target_build_swift))
config.substitutions.append(('%target-clang', config.target_clang))
config.substitutions.append(('%target-ld', config.target_ld))
if hasattr(config, 'target_cc_options'):
    config.substitutions.append(('%target-cc-options', config.target_cc_options))

config.substitutions.append(
    (r'%hardlink-or-copy\(from: *(.*), *to: *(.*)\)',
     r'ln \1 \2 || cp \1 \2'))

config.substitutions.append(('%utils', config.swift_utils))
config.substitutions.append(('%line-directive', config.line_directive))
config.substitutions.append(('%gyb', config.gyb))
config.substitutions.append(('%round-trip-syntax-test', config.round_trip_syntax_test))
config.substitutions.append(('%rth', config.rth))
config.substitutions.append(('%scale-test',
                             '{} --swiftc-binary={} --tmpdir=%t'.format(
                                 config.scale_test, config.swiftc)))
config.substitutions.append(
    ('%empty-directory\(([^)]+)\)', 'rm -rf \"\\1\" && mkdir -p \"\\1\"'))

config.substitutions.append(('%target-sil-opt', config.target_sil_opt))
config.substitutions.append(('%target-sil-func-extractor', config.target_sil_func_extractor))
config.substitutions.append(('%target-sil-llvm-gen', config.target_sil_llvm_gen))
config.substitutions.append(('%target-sil-nm', config.target_sil_nm))
config.substitutions.append(
    ('%target-swift-ide-test\(mock-sdk:([^)]+)\)',
     '%s \\1 %s -swift-version %s' %
     (subst_target_swift_ide_test_mock_sdk,
      subst_target_swift_ide_test_mock_sdk_after,
      swift_version)))
config.substitutions.append(('%target-swift-ide-test', "%s -swift-version %s" % (config.target_swift_ide_test, swift_version)))
config.substitutions.append(('%target-swift-reflection-test', lit.util.which('swift-reflection-test{variant_suffix}'.format(variant_suffix=config.variant_suffix), config.environment['PATH'])))
config.substitutions.append(('%target-swift-reflection-dump', '{} {} {}'.format(config.swift_reflection_dump, '-arch', run_cpu)))
config.substitutions.append(('%target-swiftc_driver', config.target_swiftc_driver))
config.substitutions.append(('%target-swift-remoteast-test-with-sdk',
                             '%s -sdk %s' %
                               (config.swift_remoteast_test, config.variant_sdk)))
config.substitutions.append(('%target-swift-remoteast-test', config.swift_remoteast_test))

if hasattr(config, 'target_swift_autolink_extract'):
    config.available_features.add('autolink-extract')
    config.substitutions.append(('%target-swift-autolink-extract',
                                 config.target_swift_autolink_extract))

config.substitutions.append(('%target-swift-modulewrap',
                             config.target_swift_modulewrap))

platform_module_dir = os.path.join(test_resource_dir, '%target-sdk-name', run_cpu)
lit_config.note('Using platform module dir: ' + platform_module_dir)
if test_sdk_overlay_dir is not None:
    platform_sdk_overlay_dir = os.path.join(test_sdk_overlay_dir, run_cpu)
else:
    platform_sdk_overlay_dir = platform_module_dir

config.substitutions.insert(0, ('%platform-module-dir', platform_module_dir))
config.substitutions.insert(0, ('%platform-sdk-overlay-dir', platform_sdk_overlay_dir))

config.substitutions.append(('%target-swiftmodule-name', config.target_swiftmodule_name))
config.substitutions.append(('%target-swiftdoc-name', config.target_swiftdoc_name))

config.substitutions.append(('%target-object-format', config.target_object_format))
config.substitutions.append(('%target-dylib-extension', config.target_dylib_extension))

config.substitutions.append(('%target-resilience-test-wmo', config.target_resilience_test_wmo))
config.substitutions.append(('%target-resilience-test', config.target_resilience_test))

config.substitutions.append(('%llvm-profdata', config.llvm_profdata))
config.substitutions.append(('%llvm-cov', config.llvm_cov))

config.substitutions.append(
    ('%FileCheck',
     '%s --sanitize \'BUILD_DIR=%s\' --sanitize \'SOURCE_DIR=%s\' --use-filecheck \'%s\'' %
      (config.PathSanitizingFileCheck,
       pipes.quote(swift_obj_root),
       pipes.quote(config.swift_src_root),
       pipes.quote(config.filecheck))))
config.substitutions.append(('%raw-FileCheck', pipes.quote(config.filecheck)))

# If static stdlib is present, enable static stdlib tests
static_stdlib_path = os.path.join(os.path.join(config.swift_lib_dir,"swift_static"), config.target_sdk_name)
libswiftCore_path = os.path.join(static_stdlib_path,"libswiftCore.a")
if os.path.exists(libswiftCore_path):
    config.available_features.add("static_stdlib")
    config.substitutions.append(('%target-static-stdlib-path', static_stdlib_path))
    lit_config.note('using static stdlib path: %s' % static_stdlib_path)

if config.lldb_build_root != "":
    config.available_features.add('lldb')
    # Note: using the same approach to locating the lib dir as in
    # finishSwigPythonLLDB.py in the lldb repo
    python_lib_dir = get_python_lib(True, False, config.lldb_build_root)
    config.substitutions.append(('%lldb-python-path', python_lib_dir))


# Run lsb_release on the target to be tested and return the results.
def linux_get_lsb_release():
    lsb_release_path = '/usr/bin/lsb_release'
    if os.path.isfile(lsb_release_path) and os.access(lsb_release_path, os.X_OK):
        distributor = lit.util.executeCommand([lsb_release_path, '-is'])[0].rstrip()
        release = lit.util.executeCommand([lsb_release_path, '-rs'])[0].rstrip()
        return (distributor, release)
    return ('', '')

if platform.system() == 'Linux':
    (distributor, release) = linux_get_lsb_release()
    if distributor != '' and release != '':
        config.available_features.add("LinuxDistribution=" + distributor + '-' + release)
        lit_config.note('Running tests on %s-%s' % (distributor, release))

lit_config.note("Available features: " + ", ".join(sorted(config.available_features)))
